#ifndef __EventLoop_H__
#define __EventLoop_H__

#include "MutexLock.hpp"

#include <sys/epoll.h>

#include <vector>
#include <map>
#include <memory>
#include <functional>

using std::vector;
using std::map;

namespace wd
{

class Acceptor;

class TcpConnection;
using TcpConnectionPtr=std::shared_ptr<TcpConnection>;
using TcpConnectionCallback=std::function<void(TcpConnectionPtr)>;
using Functor=std::function<void()>;

class EventLoop
{
public:
    EventLoop(Acceptor &);
    ~EventLoop();

    void loop();
    void unloop();
    void runInLoop(Functor && cb);

    void setAllCallbacks(TcpConnectionCallback && cb1,
                         TcpConnectionCallback && cb2,
                         TcpConnectionCallback && cb3)
    {
        _onConnection = std::move(cb1);
        _onMessage = std::move(cb2);
        _onClose = std::move(cb3);
    }

private:
    void waitEpollFd();

    int createEpollFd();
    void addEpollReadEvent(int fd);
    void delEpollReadEvent(int fd);

    void handleNewConnection();
    void handleMessage(int fd);

    int createEventFd();
    void handleRead();
    void wakeup();
    void doPendingFunctors();

private:
    int _epfd;
    int _eventfd;
    Acceptor & _acceptor;
    bool _isLooping;
    vector<struct epoll_event> _evtArr;
    map<int, TcpConnectionPtr> _conns;

    TcpConnectionCallback _onConnection;
    TcpConnectionCallback _onMessage;
    TcpConnectionCallback _onClose;

    vector<Functor> _pendingFunctors;
    MutexLock _mutex;
};

}//end of namespace wd


#endif

